package com.mano.mall.service.member.impl;

import com.alibaba.fastjson.JSONObject;
import com.mano.commons.web.constants.WebConstants;
import com.mano.mall.api.dto.member.input.UserLoginInpDTO;
import com.mano.mall.api.dto.member.input.UserLogoutInputDTO;
import com.mano.mall.api.member.MemberLoginService;
import com.mano.mall.common.base.BaseApiService;
import com.mano.mall.common.base.BaseResponse;
import com.mano.mall.common.constants.Constants;
import com.mano.mall.common.token.GenerateToken;
import com.mano.mall.common.transaction.RedisDataSoureceTransaction;
import com.mano.mall.common.utils.MD5Util;
import com.mano.mall.service.mapper.UserMapper;
import com.mano.mall.service.mapper.UserTokenMapper;
import com.mano.mall.service.mapper.entity.UserDO;
import com.mano.mall.service.mapper.entity.UserTokenDO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
 * @Author: zj
 * @Description:
 * @Date: Created in 15:03 2020/9/25
 * @Modified By:
 */
@RestController
public class MemberLoginServiceImpl extends BaseApiService implements MemberLoginService {


    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserTokenMapper userTokenMapper;

    @Autowired
    private GenerateToken generateToken;

    @Autowired
    private RedisDataSoureceTransaction redisDataSoureceTransaction;

    @Override
    public BaseResponse<JSONObject> login(@RequestBody @Valid UserLoginInpDTO userLoginInpDTO) {

        // 1.验证参数
        String mobile = userLoginInpDTO.getMobile();

        String password = userLoginInpDTO.getPassword();

        String loginType = userLoginInpDTO.getLoginType();


        if (!(loginType.equals(WebConstants.MEMBER_LOGIN_TYPE_ANDROID) || loginType.equals(WebConstants.MEMBER_LOGIN_TYPE_IOS)
                || loginType.equals(WebConstants.MEMBER_LOGIN_TYPE_PC))) {
            return setResultError("登陆类型出现错误!");
        }

        // 设备信息
        String deviceInfor = userLoginInpDTO.getDeviceInfor();


        String newPassWord = MD5Util.MD5(password);
        // 2.用户名称与密码登陆
        UserDO userDo = userMapper.login(mobile, newPassWord);
        if (userDo == null) {
            return setResultError("用户名称与密码错误!");
        }

        // 3.查询之前是否有过登陆
        Long userId = userDo.getUserId();
        UserTokenDO userTokenDo = userTokenMapper.selectByUserIdAndLoginType(userId, loginType);


        JSONObject tokenData = null;
        TransactionStatus status = null;
        try {
            status = redisDataSoureceTransaction.begin();
            if (userTokenDo != null) {
                // 4.清除之前的token
                String token = userTokenDo.getToken();
                // 如果开启redis事物的话，这里肯定为false
//                Boolean removeToken = generateToken.removeToken(token);
                generateToken.removeToken(token);
//                if (removeToken) {
                // 这里也要判断是否失败，需要回滚处理
                int tokenAvailability = userTokenMapper.updateTokenAvailability(token);
                if(!toDaoResult(tokenAvailability)){
                    redisDataSoureceTransaction.rollback(status);
                    return setResultError("系统错误");
                }
//                }
            }

            // openid关联用户账号信息
            String qqOpenId = userLoginInpDTO.getQqOpenId();
            if (!StringUtils.isEmpty(qqOpenId)) {
                userMapper.updateUserOpenId(qqOpenId, userId);
            }

            // 5. 生成新的token
            String newToken = generateToken.createToken(WebConstants.MEMBER_TOKEN_KEYPREFIX, userId + "",
                    WebConstants.MEMBRE_LOGIN_TOKEN_TIME);
            tokenData = new JSONObject();
            tokenData.put("token", newToken);
            // 6.存入在数据库中
            UserTokenDO userToken = new UserTokenDO();
            userToken.setUserId(userId);

            userToken.setLoginType(userLoginInpDTO.getLoginType());
            userToken.setToken(newToken);
            userToken.setDeviceInfor(deviceInfor);
            int result = userTokenMapper.insertUserToken(userToken);

            if(!toDaoResult(result)){
                redisDataSoureceTransaction.rollback(status);
                return setResultError("系统错误");
            }
            redisDataSoureceTransaction.commit(status);
            return setResultSuccess(tokenData);

        } catch (Exception e) {
            try{
                redisDataSoureceTransaction.rollback(status);

            }catch (Exception e1){

            }
            return setResultError("系统错误");
        }
    }

    @Override
    public BaseResponse<JSONObject> logout(@RequestBody @Valid UserLogoutInputDTO userLogoutInputDTO) {

        String token = userLogoutInputDTO.getToken();

        TransactionStatus status = null;

        try{
            redisDataSoureceTransaction.begin();

            //删除redis token
            generateToken.removeToken(token);

            // 更新token无效
            int tokenAvailability = userTokenMapper.updateTokenAvailability(token);
            if(!toDaoResult(tokenAvailability)){
                redisDataSoureceTransaction.rollback(status);
                return setResultError("系统错误");
            }

            redisDataSoureceTransaction.commit(status);

            return setResultSuccess("用户退出登录成功");

        }catch (Exception e){
            try{
                redisDataSoureceTransaction.rollback(status);

            }catch (Exception e1){

            }
            return setResultError("系统错误");
        }
    }
}
